home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / Wave / WavesWorld / Source / IBPalettes / WW3DKit / RIBSphere.m < prev    next >
Encoding:
Text File  |  1995-04-19  |  10.5 KB  |  399 lines

  1. // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
  2. // see COPYRIGHT for reuse legalities
  3. //
  4.  
  5. #import "RIBSphere.h"
  6. #import <stdio.h>
  7.  
  8.  
  9. @implementation RIBSphere
  10.  
  11. + initialize { return [RIBSphere setVersion:1], self; }
  12.  
  13. - (BOOL)hasBoundingBox { return YES; }
  14.  
  15. - init
  16. {
  17.   [super init];
  18.  
  19.   radius = 1.0;
  20.   zMin = -1.0;
  21.   zMax =  1.0;
  22.   
  23.   return self;
  24. }
  25.  
  26. - setRadius:(RtFloat)newRadius 
  27.      zMin:(RtFloat)newZMin zMax:(RtFloat)newZMax 
  28.      thetaMax:(RtFloat)newThetaMax
  29.      n:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector
  30.      printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
  31. {  
  32.    radius = newRadius;
  33.    zMin = newZMin;
  34.    zMax = newZMax;
  35.    if (zMin < (-1 * radius))
  36.    {  zMin = -1 * radius;
  37.    }
  38.    if (zMax > radius)
  39.    {  zMax = radius;
  40.    }
  41.  
  42.    thetaMax = newThetaMax;
  43.    [self setN:newN tokens:newTokens parms:newParms archiveVector:newArchiveVector printfTypeVector:newPrintfTypeVector printfNVector:newPrintfNVector];
  44.  
  45.    dirtyBoundingBox = TRUE;
  46.   
  47.    return self;
  48. }
  49.  
  50. - setRadius:(RtFloat)newRadius { radius = newRadius; dirtyBoundingBox = TRUE; return self; }
  51. - setZMin:(RtFloat)newZMin { zMin = newZMin; dirtyBoundingBox = TRUE; return self; }
  52. - setZMax:(RtFloat)newZMax { zMax = newZMax; dirtyBoundingBox = TRUE; return self; }
  53.  
  54. - (RtFloat)radius { return radius; } 
  55. - (RtFloat)zMin { return zMin; }
  56. - (RtFloat)zMax { return zMax; }
  57.  
  58. - calculateBoundingBoxStartingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime 
  59. {
  60.   if (thetaMax >= 180.0)
  61.   {   boundingBox[0] =  -1.0 * radius;
  62.   }
  63.   else  // less than 180
  64.   {  if (thetaMax >= 90.0)
  65.      {  boundingBox[0] =  -1.0 * radius * (RtFloat)sin((double)(toRadians((thetaMax - 90.0))));
  66.      }
  67.      else
  68.      {  //boundingBox[0] =  radius * (RtFloat)sin((double)(toRadians(thetaMax)));
  69.         boundingBox[0] = 0.0;  // this is not true if zMax or abs(zMin) is less than radius
  70.      }
  71.   }
  72.   boundingBox[1] = radius;
  73.  
  74.   if (thetaMax >= 270.0)
  75.   {  boundingBox[2] = -1.0 * radius;
  76.      boundingBox[3] = radius;
  77.   }
  78.   else
  79.   {  if (thetaMax >= 180.0)
  80.      {  boundingBox[2] = radius * sin((double)(toRadians((thetaMax))));
  81.         boundingBox[3] = radius;
  82.      }
  83.      else
  84.      {  if (thetaMax >= 90.0)
  85.         {  boundingBox[2] = 0.0;
  86.            boundingBox[3] = radius;
  87.         }
  88.         else
  89.         {  boundingBox[2] = 0.0;
  90.            boundingBox[3] = radius * sin((double)(toRadians((thetaMax))));
  91.         }
  92.      }
  93.   }
  94.  
  95.   if (zMin < 0.0)
  96.   {  if ((-1.0 * radius) < zMin)  // not a full sphere in negative Z
  97.      {  boundingBox[4] = zMin;
  98.      }
  99.      else
  100.      {  boundingBox[4] = -1.0 * radius;
  101.      }
  102.   }
  103.   else
  104.   {  boundingBox[4] = zMin;
  105.   }
  106.  
  107.   if (zMax < 0.0)
  108.   {  boundingBox[5] = zMax;
  109.   }
  110.   else
  111.   {  boundingBox[5] = radius;
  112.   }
  113.  
  114.   //fprintf(stderr, "RIBSphere bbox:\n");
  115.   //fprintf(stderr, "\t bbox : X (%f, %f)\n", boundingBox[0], boundingBox[1]);
  116.   //fprintf(stderr, "\t      : Y (%f, %f)\n", boundingBox[2], boundingBox[3]);
  117.   //fprintf(stderr, "\t      : Z (%f, %f)\n", boundingBox[4], boundingBox[5]);
  118.  
  119.   dirtyBoundingBox = FALSE; 
  120.   return self;
  121. }
  122.  
  123. - renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  124. {
  125.   RiSphereV(radius, zMin, zMax, thetaMax, n, tokens, parms);
  126.  
  127.   return self;
  128. }
  129.  
  130. - (BOOL)theSameAs:otherRIBCommand
  131. {
  132.   if (radius != [otherRIBCommand radius])
  133.   {  return NO;
  134.   }
  135.   if (zMin != [otherRIBCommand zMin])
  136.   {  return NO;
  137.   }
  138.   if (zMax != [otherRIBCommand zMax])
  139.   {  return NO;
  140.   }
  141.  
  142.   return [super theSameAs:otherRIBCommand];
  143. }
  144.  
  145.  
  146.  
  147. - (BOOL)isLerpable { return YES; }
  148.  
  149. // note: because we've made the WWSampleList "safe" for having
  150. // multiple samples with the same data, it's perfectly valid to return
  151. // yourself or b
  152. - lerpWith:b by:(float)uValue
  153. {
  154.    id      newMe = nil;
  155.    RtFloat radiusA, zMinA, zMaxA, thetaMaxA;
  156.    RtFloat radiusB, zMinB, zMaxB, thetaMaxB;
  157.  
  158.  
  159.    if (([self class] != [b class]) || (uValue <= 0.0))
  160.    {  return self;
  161.    }
  162.  
  163.    if (uValue >= 1.0)
  164.    {  return b;
  165.    }
  166.  
  167.    newMe = [super lerpWith:b by:uValue]; // this makes a copy for us
  168.  
  169.    // okay, now do the specific stuff for this class
  170.    radiusA = [self radius];
  171.    radiusB = [b radius];
  172.    [newMe setRadius:(radiusA + ((radiusB - radiusA) * uValue))]; 
  173.    zMinA = [self zMin];
  174.    zMinB = [b zMin];
  175.    [newMe setZMin:(zMinA + ((zMinB - zMinA) * uValue))];
  176.    zMaxA = [self zMax];
  177.    zMaxB = [b zMax];
  178.    [newMe setZMax:(zMaxA + ((zMaxB - zMaxA) * uValue))];
  179.    thetaMaxA = [self thetaMax];
  180.    thetaMaxB = [b thetaMax];
  181.    [newMe setThetaMax:(thetaMaxA + ((thetaMaxB - thetaMaxA) * uValue))];
  182.  
  183.    return newMe;
  184. }
  185.  
  186.  
  187. - lerpSelfWith:b by:(float)uValue
  188. {
  189.    RtFloat radiusA, zMinA, zMaxA, thetaMaxA;
  190.    RtFloat radiusB, zMinB, zMaxB, thetaMaxB;
  191.  
  192.  
  193.    if (([self class] != [b class]) || (uValue <= 0.0))
  194.    {  return self;
  195.    }
  196.  
  197.    if (uValue >= 1.0)
  198.    {  return b;
  199.    }
  200.  
  201.    [super lerpSelfWith:b by:uValue]; // this makes a copy for us
  202.  
  203.    // okay, now do the specific stuff for this class
  204.    radiusA = [self radius];
  205.    radiusB = [b radius];
  206.    [self setRadius:(radiusA + ((radiusB - radiusA) * uValue))]; 
  207.    zMinA = [self zMin];
  208.    zMinB = [b zMin];
  209.    [self setZMin:(zMinA + ((zMinB - zMinA) * uValue))];
  210.    zMaxA = [self zMax];
  211.    zMaxB = [b zMax];
  212.    [self setZMax:(zMaxA + ((zMaxB - zMaxA) * uValue))];
  213.    thetaMaxA = [self thetaMax];
  214.    thetaMaxB = [b thetaMax];
  215.    [self setThetaMax:(thetaMaxA + ((thetaMaxB - thetaMaxA) * uValue))];
  216.  
  217.    return self;
  218. }
  219.  
  220.  
  221.  
  222. - writeEve:(NXStream *)stream atTabLevel:(int)tab
  223. {
  224.    int  i;
  225.  
  226.  
  227.    for (i = 0; i < tab; i++)
  228.    {  NXPrintf(stream, "\t");
  229.    }
  230.    NXPrintf(stream, "Sphere %f %f %f %f", radius, zMin, zMax, thetaMax);
  231.    [super writeParameterList:stream];
  232.    return self;
  233. }
  234.  
  235.  
  236. - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
  237. {
  238.    RtFloat umax;
  239.    RtFloat uknots[12];
  240.    RtFloat uk[12] = { 0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1.0, 1.0, 1.0};
  241.    RtFloat vmin, vmax;
  242.    RtFloat vknots[8];
  243.    RtFloat vk[8] = { 0.0, 0.0, 0.0, 0.5, 0.5, 1.0, 1.0, 1.0};
  244.    RtFloat uspline[9][4] = { {1.0, 0.0, 1.0, 1.0},
  245.                  {M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
  246.                  {0.0, 1.0, 1.0, 1.0},
  247.                  {-M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
  248.                  {-1.0, 0.0, 1.0, 1.0},
  249.                  {-M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
  250.                  {0.0, -1.0, 1.0, 1.0},
  251.                  {M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
  252.                  {1.0, 0.0, 1.0, 1.0}};
  253.    RtFloat vspline[5][4] = { {0.0, 0.0, -1.0, 1.0},
  254.                  {M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2},
  255.                  {1.0, 1.0, 0.0, 1.0},
  256.                  {M_SQRT1_2, M_SQRT1_2, M_SQRT1_2, M_SQRT1_2},
  257.                  {0.0, 0.0, 1.0, 1.0}};
  258.    RtFloat r[4];
  259.    int i, j, k;
  260.  
  261.  
  262.    umax = [self thetaMax] / 360.0;
  263.    for (i=0; i<12; i++)
  264.     uknots[i] = uk[i] / umax;
  265.  
  266.    vmin = [self zMin] / [self radius];
  267.    vmax = [self zMax] / [self radius];
  268.    if (vmin < -1.0) vmin = -1.0;
  269.    if (vmax > 1.0) vmax = 1.0;
  270.    vmin = (asin(vmin) + M_PI_2) / M_PI;
  271.    vmax = (asin(vmax) + M_PI_2) / M_PI;
  272.    for (i=0; i<8; i++)
  273.     vknots[i] = (vk[i] - vmin) / (vmax - vmin);
  274.  
  275.    r[0] = [self radius];
  276.    r[1] = [self radius];
  277.    r[2] = [self radius];
  278.    r[3] = 1.0;
  279.  
  280.    for (i = 0; i < tab; i++)
  281.    {  NXPrintf(stream, "\t");
  282.    }
  283.    NXPrintf(stream, "# ");
  284.    [self writeEve:stream atTabLevel:0];
  285.    NXPrintf(stream, "\n");
  286.  
  287.    for (i = 0; i < tab; i++)
  288.    {  NXPrintf(stream, "\t");
  289.    }
  290.    NXPrintf(stream, "# since Inventor doesn't directly support quadrics in any terribly useful way (sigh), we turn it into a NURBS surface:\n");
  291.  
  292.    for (i = 0; i < tab; i++)
  293.    {  NXPrintf(stream, "\t");
  294.    }
  295.    NXPrintf(stream, "Separator {\n");
  296.  
  297.    for (i = 0; i < (tab+1); i++)  {  NXPrintf(stream, "\t"); }
  298.    NXPrintf(stream, "Coordinate4 {\n");
  299.    for (i = 0; i < (tab+2); i++) {  NXPrintf(stream, "\t"); }
  300.    NXPrintf(stream, "point [");
  301.  
  302.    for (i=0; i<4; i++)
  303.    {  for (j=0; j<9; j++)
  304.       {  if (!i && !j)
  305.          {  NXPrintf(stream, 
  306.              "%f %f %f %f,\n", 
  307.              (r[0] * uspline[j][0] * vspline[i][0]),
  308.              (r[1] * uspline[j][1] * vspline[i][1]),
  309.              (r[2] * uspline[j][2] * vspline[i][2]),
  310.              (r[3] * uspline[j][3] * vspline[i][3]));
  311.       }
  312.          else
  313.          {  NXPrintf(stream, 
  314.              "       %f %f %f %f,\n", 
  315.              (r[0] * uspline[j][0] * vspline[i][0]),
  316.              (r[1] * uspline[j][1] * vspline[i][1]),
  317.              (r[2] * uspline[j][2] * vspline[i][2]),
  318.              (r[3] * uspline[j][3] * vspline[i][3]));
  319.       }
  320.          for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  321.       }
  322.    }
  323.    for (j=0; j<8; j++)
  324.    {  NXPrintf(stream, 
  325.                "       %f %f %f %f,\n", 
  326.                (r[0] * uspline[j][0] * vspline[i][0]),
  327.                (r[1] * uspline[j][1] * vspline[i][1]),
  328.                (r[2] * uspline[j][2] * vspline[i][2]),
  329.                (r[3] * uspline[j][3] * vspline[i][3]));
  330.      for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  331.    }
  332.    NXPrintf(stream, 
  333.         "       %f %f %f %f]\n", 
  334.         (r[0] * uspline[j][0] * vspline[i][0]),
  335.         (r[1] * uspline[j][1] * vspline[i][1]),
  336.         (r[2] * uspline[j][2] * vspline[i][2]),
  337.         (r[3] * uspline[j][3] * vspline[i][3]));
  338.    for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  339.    NXPrintf(stream, "}\n");
  340.  
  341.    for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  342.    NXPrintf(stream, "NurbsSurface {\n");
  343.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  344.    NXPrintf(stream, "numUControlPoints 9\n");
  345.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  346.    NXPrintf(stream, "numVControlPoints 5\n");
  347.  
  348.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  349.    NXPrintf(stream, "uKnotVector [");
  350.    for (i=0; i<11; i++)
  351.    {    NXPrintf(stream, "%f, ", uknots[i]);
  352.    }
  353.    NXPrintf(stream, "%f]\n", uknots[i]);
  354.  
  355.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  356.    NXPrintf(stream, "vKnotVector [");
  357.    for (i=0; i<7; i++)
  358.    {    NXPrintf(stream, "%f, ", vknots[i]);
  359.    }
  360.    NXPrintf(stream, "%f]\n", vknots[i]);
  361.    for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  362.    NXPrintf(stream, "}\n");
  363.    for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  364.    NXPrintf(stream, "}\n");
  365.  
  366.    return self;
  367. }
  368.  
  369. #define typeVector "fff"
  370. #define typeValues &radius, &zMin, &zMax
  371.  
  372. - read:(NXTypedStream*)stream 
  373. {
  374.     int version;
  375.     [super read:stream];
  376.  
  377.     version = NXTypedStreamClassVersion(stream,"RIBSphere");
  378.     if (version == 0) NXReadTypes(stream,"i",&version), version=1;
  379.     if (version == 1)
  380.     {  NXReadTypes(stream,typeVector,typeValues);
  381.     } 
  382.     else 
  383.     {
  384.     }
  385.     return self;
  386. }
  387.  
  388. - write:(NXTypedStream*)stream 
  389. {
  390.     [super write:stream];
  391.  
  392.     NXWriteTypes(stream,typeVector, typeValues);
  393.  
  394.     return self;
  395. }
  396.  
  397.  
  398. @end
  399.